#include <sys/epoll.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <memory>
#include "http/cwhttprequest.h"
#include "http/cwhttpreply.h"
#include "business/businessfactory.h"

// 缓冲区2K
const unsigned int kBuffer_size = 2048;
// 服务器端口8899
const unsigned short kPort = 8899;
// epoll最大事件
const unsigned short kEpollEvents_size = 256;

void initServer(int &server_socket, struct sockaddr_in &serverAddr, int &epoll_fd, epoll_event &ev)
{
    server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket == -1)
    {
        printf("创建服务端套接字失败...\n");
        exit(0);
    }

    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(kPort);
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(server_socket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1)
    {
        printf("服务端绑定地址端口失败...\n");
        close(server_socket);
        exit(0);
    }

    if (listen(server_socket, 1024) == -1)
    {
        printf("服务端监听失败...\n");
        close(server_socket);
        exit(0);
    }

    epoll_fd = epoll_create(1);
    ev.data.fd = server_socket;
    ev.events = EPOLLIN;
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_socket, &ev);
}

int main()
{
    int server_socket, i, fd, nums, epoll_fd;
    struct sockaddr_in serverAddr;
    char recv_buffer[kBuffer_size];
    epoll_event ev, evs[kEpollEvents_size];
    initServer(server_socket, serverAddr, epoll_fd, ev);

    printf("==========服务器开启成功==========\n");

    while (true)
    {
        nums = epoll_wait(epoll_fd, evs, kEpollEvents_size, -1);
        if (nums <= 0)
            continue;
        for (i = 0; i < nums; ++i)
        {
            fd = evs[i].data.fd;
            if (fd == server_socket)
            {
                int client_socket = accept(server_socket, nullptr, nullptr);
                ev.data.fd = client_socket;
                ev.events = EPOLLIN;
                epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_socket, &ev);
            }
            else
            {
                memset(recv_buffer, 0, kBuffer_size);
                size_t recv_size = recv(fd, recv_buffer, kBuffer_size - 1, 0);
                if (recv_size <= 0)
                {
                    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, nullptr);
                    close(fd);
                }
                else
                {
                    // 检查是否为HTTP请求
                    if (strncmp(recv_buffer, "GET", 3) == 0 || strncmp(recv_buffer, "POST", 4) == 0)
                    {
                        size_t send_size = 0;
                        std::cout << recv_buffer << std::endl;
                        std::string msg = recv_buffer;
                        CWHttpRequest request(msg);
                        BusinessFactory factory;
                        std::shared_ptr<Business> business(factory.createBusiness(request));
                        if (business.get() != nullptr)
                        {
                            // 执行业务
                            CWHttpReply reply = business->doBusiness(request);
                            // 发送HTTP回复
                            std::string str_reply = reply.toStdString();
                            // std::cout << str_reply << std::endl;
                            send_size = send(fd, str_reply.c_str(), str_reply.size(), 0);
                        }
                        // 回复http请求后断开连接
                        epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, nullptr);
                        close(fd);
                    }
                    else // 不是HTTP请求
                    {
                    }
                }
            }
        }
    }
    close(server_socket);
    return 0;
}